package com.nuoniu.sibanyun.service.crm.call.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.constant.OrderConstant;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.DateUtils;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.SysCompany;
import com.nuoniu.sibanyun.entity.crm.call.CrmCallAgent;
import com.nuoniu.sibanyun.entity.crm.call.dto.*;
import com.nuoniu.sibanyun.entity.crm.call.vo.CrmCallAgentCustomerVo;
import com.nuoniu.sibanyun.entity.crm.call.vo.CrmCallAgentUserVo;
import com.nuoniu.sibanyun.entity.expenses.ExpensesBusinessOrder;
import com.nuoniu.sibanyun.entity.expenses.ExpensesProperty;
import com.nuoniu.sibanyun.entity.vo.SelectVo;
import com.nuoniu.sibanyun.mapper.crm.call.CrmCallAgentMapper;
import com.nuoniu.sibanyun.service.ISysCompanyService;
import com.nuoniu.sibanyun.service.crm.call.ICrmCallAgentService;
import com.nuoniu.sibanyun.service.crm.call.ICrmCallAgentStatisticsService;
import com.nuoniu.sibanyun.service.expenses.IExpensesBusinessOrderService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 客户管理-坐席 服务实现类
 * </p>
 *
 * @author 白强
 * @since 2022-04-15
 */
@Service
@Log4j2
public class CrmCallAgentServiceImpl extends ServiceImpl<CrmCallAgentMapper, CrmCallAgent> implements ICrmCallAgentService {

    @Autowired
    private IExpensesBusinessOrderService businessOrderService;
    @Autowired
    private ICrmCallAgentStatisticsService agentStatisticsService;
    @Autowired
    private ISysCompanyService sysCompanyService;

    @Override
    public Page<CrmCallAgent> pageCrmCallAgentBySystem(CrmCallAgentSearchDto crmCallAgentSearchDto) {
        Page<CrmCallAgent> crmCallAgentVoPage = baseMapper.pageCrmCallAgentBySystem(crmCallAgentSearchDto.getPage(), crmCallAgentSearchDto);
        return crmCallAgentVoPage;
    }

    @Override
    public void saveCrmCallAgent(CrmCallAgent crmCallAgent) {
        Integer companyId = crmCallAgent.getCompanyId();
        if(null == companyId)throw new NuoNiuException("请分配租户");
        UserInfo userInfo = UserThreadLocal.get();
        Long id = crmCallAgent.getId();
        String loginAccount = crmCallAgent.getLoginAccount();
        String tenantName = crmCallAgent.getTenantName();
        if(StringUtils.isBlank(loginAccount) || StringUtils.isBlank(tenantName))throw new NuoNiuException("登录账户 或者 公司名称不能为空");
        int count = checkAgent(loginAccount, tenantName, id);
        if(count > 0)throw new NuoNiuException("登录账户重复");
        if(null == id){
            crmCallAgent.setCreateUserId(userInfo.getUserId());
            crmCallAgent.setCreateUserName(userInfo.getRealName());
            crmCallAgent.setCreateDate(LocalDateTime.now());
            crmCallAgent.setStatus(0);
        }
        saveOrUpdate(crmCallAgent);
    }

    @Override
    public int checkAgent(String loginAccount, String tenantName, Long oldId) {
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_account",loginAccount);
        queryWrapper.eq("tenant_name",tenantName);
        if(null != oldId){
            queryWrapper.ne("id",oldId);
        }
        return count(queryWrapper);
    }

    /**
     * 批量删除 坐席(超级管理员) 逻辑删除
     * @param dto
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByIds(IdsAndCompanyIdDto dto) {
        List<Long> ids = dto.getIds();
        Integer companyId = dto.getCompanyId();
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        int checkStatus = batchCheckStatus(ids, 0);
        if(checkStatus != ids.size())throw new NuoNiuException("坐席已启用，不能删除");
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",ids);
        remove(queryWrapper);

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchEnable(IdsAndCompanyIdDto dto) {
        List<Long> ids = dto.getIds();
        Integer companyId = dto.getCompanyId();
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        int checkStatus = batchCheckStatus(ids, 0);
        if(ids.size() != checkStatus)throw new NuoNiuException("请选择未启用的记录");
        batchUpdateStatus(ids,1);
        /** 更新 坐席统计数据 */
        agentStatisticsService.checkAgentStatistics(companyId);
    }

    @Override
    public void batchDisable(IdsAndCompanyIdDto dto) {
        List<Long> ids = dto.getIds();
        Integer companyId = dto.getCompanyId();
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        int checkStatus = batchCheckStatus(ids, 1);
        if(ids.size() != checkStatus)throw new NuoNiuException("请选择已启用的记录");
        batchUpdateStatus(ids,2);
        /** 更新 坐席统计数据 */
        agentStatisticsService.checkAgentStatistics(companyId);
    }

    @Override
    public void batchUpdateStatus(List<Long> ids, Integer status) {
        if(null == ids || ids.size() == 0 || null == status)throw new NuoNiuException("参数错误");
        UpdateWrapper<CrmCallAgent> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",ids);
        updateWrapper.set("status",status);
        update(updateWrapper);
    }

    @Override
    public int batchCheckStatus(List<Long> ids, Integer status) {
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        if(null != status){
            queryWrapper.eq("status",status);
        }
        queryWrapper.in("id",ids);
        int count = count(queryWrapper);
        return count;
    }

    @Override
    public Page<CrmCallAgentCustomerVo> pageCrmCallAgentCustomerVo(CrmCallAgentSearchDto crmCallAgentSearchDto) {
        UserInfo userInfo = UserThreadLocal.get();
        crmCallAgentSearchDto.setCompanyId(userInfo.getCompanyId());
        Page<CrmCallAgentCustomerVo> crmCallAgentCustomerVoPage = baseMapper.pageCrmCallAgentCustomerVo(crmCallAgentSearchDto.getPage(), crmCallAgentSearchDto);
        return crmCallAgentCustomerVoPage;
    }


    @Override
    public void distributeAgent(Long agentId, Long userId,String userName) {
        if(null == agentId || null == userId)throw new NuoNiuException("参数错误");
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        UpdateWrapper<CrmCallAgent> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("binding_user_id",0);
        updateWrapper.set("binding_user_name","");
        updateWrapper.set("binding_date",null);
        updateWrapper.eq("binding_user_id",userId);
        updateWrapper.eq("company_id", companyId);
        update(updateWrapper);
        UpdateWrapper<CrmCallAgent> updateWrapper2 = new UpdateWrapper<>();
        updateWrapper2.set("binding_user_id",userId);
        updateWrapper2.set("binding_user_name",userName);
        updateWrapper2.set("binding_date",LocalDateTime.now());
        updateWrapper2.eq("id",agentId);
        updateWrapper2.eq("company_id", companyId);
        update(updateWrapper2);
    }

    @Override
    public int checkData(CrmCallAgent crmCallAgent) {
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>(crmCallAgent);
        return count(queryWrapper);
    }

    @Override
    public List<SelectVo> selectNotDistributeUser() {
        UserInfo userInfo = UserThreadLocal.get();
        return baseMapper.selectNotDistributeUser(userInfo.getCompanyId());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveAgentOrder(AgentOrderDto agentOrderDto) {
        UserInfo userInfo = UserThreadLocal.get();
        LocalDateTime now = LocalDateTime.now();
        Integer number = agentOrderDto.getNumber();
        BigDecimal price = agentOrderDto.getPrice();
        String productionName = "新购坐席"+ number + "个";
        BigDecimal amount = price.multiply(new BigDecimal(number));
        /** 组装业务订单*/
        ExpensesBusinessOrder businessOrder = new ExpensesBusinessOrder();
        businessOrder.setCreateTime(now);
        businessOrder.setCreateUserId(userInfo.getUserId());
        businessOrder.setCreateUserName(userInfo.getRealName());
        businessOrder.setPayTime(now);
        businessOrder.setPayUserId(userInfo.getUserId());
        businessOrder.setPayUserName(userInfo.getUserName());
        businessOrder.setBusinessType(1);
        businessOrder.setProductionType("callAgent");
        businessOrder.setProductionName(productionName);
        businessOrder.setOrderAmount(amount);
        businessOrder.setPrice(amount);
        businessOrder.setTimeUnit("月");
        businessOrder.setTimeNumber(1);
        businessOrder.setOrderType(1);
        businessOrder.setPaymentType(1);
        businessOrder.setStatus(3);
        businessOrder.setProductionSpecifications(JSON.toJSONString(agentOrderDto));
        businessOrderService.addBusinessOrder(businessOrder);
        /** 校验并初始化数据 */
        agentStatisticsService.checkFromAddAgent(number);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void dealAgentOrder(DealAgentOrderDto dealAgentOrderDto) {
        List<Long> ids = dealAgentOrderDto.getIds();
        Integer companyId = dealAgentOrderDto.getCompanyId();
        Integer orderId = dealAgentOrderDto.getOrderId();
        int count = this.batchCheckStatus(ids, 0);
        if(count != ids.size())throw new NuoNiuException("参数错误");
        this.batchUpdateStatus(ids,1);
        /** 坐席订单 交易成功 */
        businessOrderService.dealAgentOrder(ids,orderId);
        /** 更新 坐席统计数据 */
        agentStatisticsService.checkAgentStatistics(companyId);
    }

    /**
     * 批量 开启/关闭 坐席
     * @param closeExpensesPropertyList
     * @param status 1:生效（开启） 2.暂停（关闭）
     * @return
     */
    @Override
    public void batchUpdateAgentFromExpensesProperty(List<ExpensesProperty> closeExpensesPropertyList, Integer status) {
        List<Long> agentIdList = new ArrayList<>();
        Set<Integer> companyIdSet = new HashSet<>();
        int size = closeExpensesPropertyList.size();
        for (int i = 0; i < size; i++) {
            ExpensesProperty expensesProperty = closeExpensesPropertyList.get(i);
            String productionSpecifications = expensesProperty.getProductionSpecifications();
            AgentOrderDto agentOrderDto = JSON.parseObject(productionSpecifications, AgentOrderDto.class);
            List<Long> agentIds = agentOrderDto.getAgentIds();
            agentIdList.addAll(agentIds);
            companyIdSet.add(expensesProperty.getCompanyId());
        }
        if(agentIdList.size() > 0){
            log.info("批量{}坐席数量{}",status.equals(1) ? "开启":"关闭",agentIdList.size());
            UpdateWrapper<CrmCallAgent> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("id",agentIdList);
            updateWrapper.set("status",status);
            update(updateWrapper);
            /** 批量更新 坐席 是否需要 校验 */
            agentStatisticsService.batchUpdateCompanyList(companyIdSet);
        }
    }

    /**
     * 坐席用户分配情况
     * @param dto
     * @return
     */
    @Override
    public Page<CrmCallAgentUserVo> pageCrmCallAgentUserVo(CrmCallAgentUserDto dto) {
        UserInfo userInfo = UserThreadLocal.get();
        Page page = dto.getPage();
        Page<CrmCallAgentUserVo> crmCallAgentUserVoPage = baseMapper.pageCrmCallAgentUserVo(page, userInfo.getCompanyId(), dto);
        return crmCallAgentUserVoPage;
    }

    @Override
    public void saveAgentByCompany(CrmCallAgent crmCallAgent) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        SysCompany sysCompany = sysCompanyService.getById(companyId);
        Integer companyUser = sysCompany.getCompanyUser();
        Long id = crmCallAgent.getId();
        String phone = crmCallAgent.getPhone();
        String loginAccount = crmCallAgent.getLoginAccount();
        String tenantName = crmCallAgent.getTenantName();
        Integer bindingUserId = crmCallAgent.getBindingUserId();
        if(null == bindingUserId )throw new NuoNiuException("绑定的用户不能为空");
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",companyId);
        int totalAgent = count(queryWrapper);
        if(totalAgent >= companyUser)throw new NuoNiuException("可开通坐席数量已达到最大值:"+ companyUser);
        if(StringUtils.isNotBlank(loginAccount) && StringUtils.isNotBlank(phone)){
            queryWrapper.and(wrapper -> wrapper.eq("binding_user_id", bindingUserId).or().eq("login_account", loginAccount).or().eq("phone", phone));
        }else if(StringUtils.isNotBlank(loginAccount)){
            queryWrapper.and(wrapper -> wrapper.eq("binding_user_id", bindingUserId).or().eq("login_account", loginAccount));
        }else if(StringUtils.isNotBlank(phone)){
            queryWrapper.and(wrapper -> wrapper.eq("binding_user_id", bindingUserId).or().eq("phone", phone));
        }else{
            queryWrapper.eq("binding_user_id", bindingUserId);
        }
        if(null != id){
            queryWrapper.ne("id", id);
        }
        int count = count(queryWrapper);
        if(count > 0){
            if(StringUtils.isNotBlank(loginAccount) && StringUtils.isNotBlank(phone)){
                throw new NuoNiuException("绑定的用户 或者 坐席账户 或者 绑定电话 不能重复");
            }
            else if(StringUtils.isNotBlank(phone)){
                throw new NuoNiuException("绑定的用户 或者 绑定电话 不能重复");
            }
            else if(StringUtils.isNotBlank(loginAccount)){
                throw new NuoNiuException("绑定的用户 或者 坐席账户 不能重复");
            }else{
                throw new NuoNiuException("绑定的用户 不能重复");
            }
        }

        if(null == id){
            crmCallAgent.setCreateUserId(userInfo.getUserId());
            crmCallAgent.setCreateUserName(userInfo.getRealName());
            crmCallAgent.setCreateDate(LocalDateTime.now());
            crmCallAgent.setCompanyId(companyId);
            crmCallAgent.setStatus(1);
        }
        saveOrUpdate(crmCallAgent);
    }

    @Override
    public void batchEnableByCompany(List<Long> ids) {
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        batchUpdateStatus(ids,1);
    }

    @Override
    public void batchDisableByCompany(List<Long> ids) {
        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
        batchUpdateStatus(ids,2);
    }

    @Override
    public void deleteByIdsByCompany(List<Long> ids) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
//        if(null == ids || ids.size() == 0)throw new NuoNiuException("参数错误");
//        int checkStatus = batchCheckStatus(ids, 0);
//        if(checkStatus != ids.size())throw new NuoNiuException("坐席已启用，不能删除");
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",companyId);
        queryWrapper.in("id",ids);
        remove(queryWrapper);
    }

    @Override
    public CrmCallAgent getMyCrmCallAgent() {
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("binding_user_id",userInfo.getUserId());
        queryWrapper.eq("status",1);
        queryWrapper.last("LIMIT 1");
        CrmCallAgent callAgent = getOne(queryWrapper, false);
        return callAgent;
    }

    @Override
    public CrmCallAgent getByPhone(String phone) {
        if(StringUtils.isBlank(phone))return null;
        QueryWrapper<CrmCallAgent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        queryWrapper.last("LIMIT 1");
        CrmCallAgent callAgent = getOne(queryWrapper, false);
        return callAgent;
    }



}
